home *** CD-ROM | disk | FTP | other *** search
/ NetNews Offline 2 / NetNews Offline Volume 2.iso / news / comp / lang / c++-part2 / 17455 < prev    next >
Encoding:
Internet Message Format  |  1996-08-05  |  5.4 KB

  1. Path: bcarh8ab.bnr.ca!jcobban
  2. From: jcobban@bnr.ca (Jim Cobban)
  3. Newsgroups: comp.lang.c++
  4. Subject: Deriving class from IOSTREAMs
  5. Date: 15 Apr 1996 19:59:06 GMT
  6. Organization: Bell-Northern Research Canada
  7. Message-ID: <4ku9qa$7mt@bcarh8ab.bnr.ca>
  8. Reply-To: jcobban@nortel.ca (Jim Cobban)
  9. NNTP-Posting-Host: bcarsf1f.bnr.ca
  10.  
  11. I am trying to define a class which has the following characteristics:
  12.  
  13.   1) It supports the insertion (<<) operator of the ostream class.
  14.   2) Output is organized into units of work.  No part of a unit of work
  15.      can be written to the output device until the unit of work is complete.
  16.      Then all of the text in the unit of work must be placed on the same line
  17.      of output.  In other words if there is enough room on the current line
  18.      to hold all of the text then it will be printed on the current line,
  19.      otherwise a new line is started and the text is written on the new line.
  20.   3) When a new line is started, including the very first line in the output,
  21.      an application specified prefix is written before the first unit of
  22.      work.
  23.  
  24. The first requirement dictates that my class be derived directly or
  25. indirectly from ostream.  The second requirement seems to me to dictate that
  26. my class be derived, in particular, from ostrstream, which provides a buffer
  27. in which output can be held until a unit of work is complete.  I would like
  28. the end of a unit of work to be signalled by a manipulator, but I have had a
  29. great deal of difficulty in getting that to work.
  30.  
  31. A stripped down sample program which illustrates some of the problems I am
  32. having follows:
  33.  
  34.     10  #include <strstream.h>
  35.     11
  36.     12  class xstream : public ostrstream
  37.     13  {
  38.     14    char          buffer[80];
  39.     15
  40.     16    public:
  41.     17
  42.     18    xstream();
  43.     19    friend ostream& operator <<(ostream& Ostream, ostream & (*
  44. func)(xstream &))\
  45.     20          { return (*func)((xstream &)Ostream); }
  46.     21  };              //* end of declaration of class xstream
  47.     22
  48.     23  xstream::xstream()
  49.     24  {
  50.     25    rdbuf()->setbuf(buffer, sizeof(buffer));
  51.     26  }
  52.     27
  53.     28  ostream & endw(xstream & Stream)
  54.     29  {
  55.     30    Stream << ends;
  56.     31    cout << "pcount=" << Stream.pcount() << " \"" << Stream.str() <<
  57. "\"" << endl;
  58.     32    Stream.seekp(0, ios::beg);
  59.     33    return Stream;
  60.     34  }
  61.     35
  62.     36  int main()
  63.     37  {
  64.     38    xstream       os;
  65.     39    double        pi=3.14159;
  66.     40
  67.     41    cout << "pi=" << pi << " and so on" << endl;
  68.     42    os << "pi=" << pi << " and so on" << endw;
  69.     43    os << "testing" << endw;
  70.     44    os << "short" << endw;
  71.     45    os << "testing " << 5 << " more";
  72.     46    cout << "outside os.pcount()=" << os.pcount() << endl;
  73.     47    os << endw;
  74.     48  }
  75.  
  76. The first problem is that the behavior of my manipulator for signalling the
  77. end of a unit of work is dependent upon access to methods of the xstream
  78. class (In the example these are all methods of the ostrstream class, but that
  79. is because I haven't included the code for printing the prefix in this
  80. example).  But normal manipulators, like endl, take an ostream as their
  81. parameter.  So I have the ugly, dangerous, cast in the definition of the
  82. operator << in line 19, which exists only to convince C++ to call endw.  I
  83. say dangerous because there is nothing to prevent the endw manipulator from
  84. being called for any output stream.  As a specific example the statement
  85. "cout << endw;" compiles cleanly, but would crash because the stream is not
  86. actually an ostrstream.  But the only alternatives I can see are:
  87.  
  88.   1) invoke endw as a member function of xstream, rather than as a
  89.      manipulator, which is syntactically clumsy.
  90.   2) redefine all of the inserters under xstream so that they return
  91.      references to xstream rather than to ostream, something I can't do
  92.      because the original operators were not defined as virtual, for obvious
  93.      performance reasons.
  94.  
  95. Quite aside from that, although the above example compiles cleanly, it does
  96. not produce the expected output, for reasons which escape me.  The actual
  97. output is:
  98.  
  99. pi=3.14159 and so on
  100. pcount=-268438404 "pi=3"
  101. pcount=-268438407 ""
  102. pcount=-268438407 ""
  103. outside os.pcount()=0
  104. pcount=-268438407 ""
  105.  
  106. The first line is the result of line 41 above.  The lines starting with
  107. pcount are produced by the endw manipulator.  There are a couple of glaring
  108. problems:
  109.  
  110.   1) the value of pcount is garbage.
  111.   2) the inherited inserters don't seem to work, starting with the 
  112.      inserter for double which stopped after putting out one digit.  Nothing
  113.      comes out for any subsequent inserter.
  114.   3) if I omit using the double inserter then in other examples I got
  115.      more reasonable output, except that the ends manipulator seemed
  116.      incapable of shortening the string.  For example if I deleted lines 41
  117.      and 42 from the test program then the output of lines 43 and 44 is
  118.  
  119. pcount=-268438401 "testing"
  120. pcount=-268438403 "shortng"
  121.  
  122. If I cannot quickly resolve this bizarre behavior then I am simply going to
  123. conclude that the C++ IOSTREAMS system is completely fucked up, and go back
  124. to using printf.
  125. -- 
  126. Jim Cobban   |  jcobban@nortel.ca                   |  Phone: (613) 763-8013
  127. Nortel (MCS) |                                      |  FAX:   (613) 763-5199
  128. |                                                                             |
  129. |   The opinions expressed are those of the author and do not necessarily     |
  130. |   represent the opinions of Nortel.                                         |
  131.